<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/13
 * Time: 11:25
 */

namespace app\api\Service;

use app\common\model\BetsRecord;
use app\common\model\LotteryDota2;
use app\common\model\LotteryLol;
use app\common\model\LotteryPvp;
use app\common\model\Wallet;
use app\common\library\Auth;
use app\common\model\Config;
use app\common\model\WalletRecord;
use app\common\model\WalletLog;
use think\Db;
use app\common\model\Bets;
use app\common\model\WallertMultiple;
use think\Queue;

class UserService
{

    public $auth;
    public $fptime;//封盘时间
    public $websocket;
    public $pvpfptime;

    public $agentService;
    public function __construct()
    {
        $this->websocket = new WebsocketService();
        $this->auth = Auth::instance();
        $this->agentService = new AgentService();
        $this->fptime = [
            [date('Y-m-d H:00:02',time()),date('Y-m-d H:00:11',time())],
            [date('Y-m-d H:03:22',time()),date('Y-m-d H:03:31',time())],
            [date('Y-m-d H:06:42',time()),date('Y-m-d H:06:51',time())],

            [date('Y-m-d H:10:02',time()),date('Y-m-d H:10:11',time())],
            [date('Y-m-d H:13:22',time()),date('Y-m-d H:13:31',time())],
            [date('Y-m-d H:16:42',time()),date('Y-m-d H:16:51',time())],

            [date('Y-m-d H:20:02',time()),date('Y-m-d H:20:11',time())],
            [date('Y-m-d H:23:22',time()),date('Y-m-d H:23:31',time())],
            [date('Y-m-d H:26:42',time()),date('Y-m-d H:26:51',time())],

            [date('Y-m-d H:30:02',time()),date('Y-m-d H:30:11',time())],
            [date('Y-m-d H:33:22',time()),date('Y-m-d H:33:31',time())],
            [date('Y-m-d H:36:42',time()),date('Y-m-d H:36:51',time())],

            [date('Y-m-d H:40:02',time()),date('Y-m-d H:40:11',time())],
            [date('Y-m-d H:43:22',time()),date('Y-m-d H:43:31',time())],
            [date('Y-m-d H:46:42',time()),date('Y-m-d H:46:51',time())],

            [date('Y-m-d H:50:02',time()),date('Y-m-d H:50:11',time())],
            [date('Y-m-d H:53:22',time()),date('Y-m-d H:53:31',time())],
            [date('Y-m-d H:56:42',time()),date('Y-m-d H:56:51',time())],
        ];
        $this->lolfptime = [
            [date('Y-m-d H:04:52',time()),date('Y-m-d H:05:01',time())],
            [date('Y-m-d H:09:52',time()),date('Y-m-d H:10:01',time())],

            [date('Y-m-d H:14:52',time()),date('Y-m-d H:15:01',time())],
            [date('Y-m-d H:19:52',time()),date('Y-m-d H:20:01',time())],

            [date('Y-m-d H:24:52',time()),date('Y-m-d H:25:01',time())],
            [date('Y-m-d H:29:52',time()),date('Y-m-d H:30:01',time())],

            [date('Y-m-d H:34:52',time()),date('Y-m-d H:35:01',time())],
            [date('Y-m-d H:39:52',time()),date('Y-m-d H:40:01',time())],

            [date('Y-m-d H:44:52',time()),date('Y-m-d H:45:01',time())],
            [date('Y-m-d H:49:52',time()),date('Y-m-d H:50:01',time())],

            [date('Y-m-d H:54:52',time()),date('Y-m-d H:55:01',time())],
            [date('Y-m-d H:59:52',time()),date('Y-m-d H:00:01',time())],
        ];
    }

    /**
     * 下注
     * @param $data
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function betting($data)
    {
        $betContent = [];
        unset($data['token']);
        $wallet = Wallet::where('user_id',$this->auth->id)->find();
        $config = collection(Config::where('group','=','publiconfig')->field('name,value')->select())->toArray();
        $betConfig = [];
        if( $config ){
            if( $this->isfp($data['game']) == true){
                return ['code'=>203,'msg'=>'已封盘不能投注！'];
            }
            foreach ( $config as $item ){
                $betConfig[$item['name']] = $item['value'];
            }
//            if( $betConfig['bets_min'] > $data['allmoney'] ){
//                return ['code'=>201,'msg'=>'最小投注金额为'.$betConfig['bets_min']];
//            }
//            if( $betConfig['bets_max'] < $data['allmoney'] ){
//                return ['code'=>202,'msg'=>'最大投注金额为'.$betConfig['bets_max']];
//            }

            if( $data['game'] == 'lol' ){
                $betIndex = LotteryLol::get($data['sequencenum']);
            }elseif( $data['game'] == 'pvp' ){
                $betIndex = LotteryPvp::get($data['sequencenum']);
            }elseif( $data['game'] == 'dota2' ){
                $betIndex = LotteryDota2::get($data['sequencenum']);
            }

            if( !$betIndex || $betIndex->status != 0 ){
                return ['code'=>205,'msg'=>'投注期号有误！'];
            }
        }

        if( $wallet['money'] < $data['allmoney'] ){
            return ['code'=>204,'msg'=>'余额不足，请充值！'];
        }

        $userinfo = $this->auth->getUserinfo();

        $now = time();
        Db::startTrans();
        try {
            foreach ( $data as $k=>$v ){
                if( set_type_name($k) && $v > 0){
                    $betContent[$k] = set_type_name($k);

                    if( $userinfo['pid'] && $userinfo['pid'] > 0 ){ //为代理分红
                        $this->agentService->updateMoneyToAgent($userinfo['username'],$userinfo['pid'],$v);
                    }

                    $walletService = new WalletService();
                    $recordSn = $walletService->saveWallet(-$v,$this->auth->id,3,'下注',1,$data['sequencenum']);

                    Bets::insert([//用户下注记录
                        'sequencenum'   => $data['sequencenum'],            //期号
                        'order_sn'      => Bets::getOrderSn($data['game']),
                        'user_id'       => $this->auth->id,
                        'content'       => json_encode([$k=>$v]),  //下注内容
                        'money'         => $v,               //下注总金额
                        'addtime'       => $now,                          //下注时间
                        'game'          => $data['game'],                   //游戏
                        'ip'            => request()->ip(),                 //ip
                        'createtime'    => $now,
                        'site'          => $this->auth->site,
                        'role'          => $this->auth->group_id,
                    ]);
                    $walletService->recordWaterMultiple($this->auth->id,'下注',$recordSn,$v);
                }
            }
            Db::commit();
            if( $this->auth->group_id == 2 ){ //普通用户下注，分析投注平衡关闭
                //1.当前任务将由哪个类来负责处理
                //$jobHandlerClassName = 'app\api\job\InjectionBetsRecord';
                //$jobQueueName  	  = "betRecordQueue";
                // 3.当前任务所需的业务数据 . 不能为 resource 类型，其他类型最终将转化为json形式的字符串
                //   ( jobData 为对象时，需要在先在此处手动序列化，否则只存储其public属性的键值对)
                // 4.将该任务推送到消息队列，等待对应的消费者去执行
                //Queue::push( $jobHandlerClassName , $data , $jobQueueName );
                //$this->updateBetsRecord($data);//修改总投注记录（用户计算每一期投注总量）
            }

            return ['code'=>200,'msg'=>'下注成功！','balance'=>Wallet::where('user_id',$this->auth->id)->value('money')];
        }catch ( \Exception $e ){
            file_put_contents(
                BETTING_ERROR_PATH,
                '【' . date( 'Y-m-d H:i:s', $_SERVER[ 'REQUEST_TIME' ] ) . '】  用户下注：'.$e. PHP_EOL,
                FILE_APPEND
            );
            Db::rollback();
            return ['code'=>500,'msg'=>'下注失败！'];
        }

    }

    /**
     * 撤单
     * @param $game
     * @param $order_sn
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function revoke($game,$order_sn)
    {
        if ( $this->isfp($game) ){
            return ['code'=>'206','msg'=>'正在开奖，撤单失败！'];
        }
        $wallet = Wallet::where('user_id',$this->auth->id)->find();
        $now = time();
        $bet = Bets::where('order_sn',$order_sn)->whereNull('status')->find();
        if($bet ){
            Db::startTrans();
            try {
                $bet->status = 3;
                $bet->updatetime = $now;
                $bet->save();

                $wallet->money  = $wallet['money'] + $bet['money'];//钱包添加余额
                $wallet->site   = $this->auth->site;
                $wallet->save();

                $walletService = new WalletService();
                //记录资金流向
                $recordSn = $walletService->saveWallet($bet['money'],$this->auth->id,12,'撤单',1);

                $waterMultiple = new WallertMultiple();
                //返还流水
                $lastwater = $waterMultiple::where('user_id',$this->auth->id)
                    ->order('id','desc')->limit(1)->field('surpluswate,beallwate')->find();//记录流水

                $surplusum = $lastwater ? $lastwater['surpluswate'] : 0;
                $beallwate = $lastwater ? $lastwater['beallwate'] : 0;
                $waterMultipleData = [
                    'remark'    => '撤单',
                    'record_sn' => $recordSn,
                    'change_money' => $bet['money'],
                    'beallwate' => $beallwate,
                    'surpluswate'=> $surplusum + $bet['money'],
                    'user_id'   => $this->auth->id,
                    'type'      => 12
                ];
                $waterMultiple->data($waterMultipleData)->save();
                //WaterMultiple::where('user_id',$this->auth->id)->where('order_sn',$order_sn)->delete();
                Db::commit();
                return ['code'=>200,'msg'=>'撤单成功！'];
            }catch ( \Exception $e ){
                file_put_contents(
                    REVOKE_ERROR_PATH,
                    '【' . date( 'Y-m-d H:i:s', $_SERVER[ 'REQUEST_TIME' ] ) . '】  撤单失败：'.$e. PHP_EOL,
                    FILE_APPEND
                );
                Db::rollback();
                return ['code'=>500,'msg'=>'服务器异常，稍后再试！'];
            }

        }else{
            return ['code'=>207,'msg'=>'该订单不允许撤销'];
        }

    }

    /**
     * 是否是封盘时间
     */
    public function isfp($game)
    {
        $now = time();
        if( $game == 'dota2' ){
            foreach ( $this->fptime as $item ){
                if( $now >= strtotime($item[0]) && $now <= strtotime($item[1]) ){
                    $isfp = true;
                    break;
                }else{
                    $isfp = false;
                }
            }
        }
        if($game == 'lol'){
            foreach ( $this->lolfptime as $item ){
                if( $now >= strtotime($item[0]) && $now <= strtotime($item[1]) ){
                    $isfp = true;
                    break;
                }else{
                    $isfp = false;
                }
            }
        }
        if( $game == 'pvp' ){
            $s = date('s',time());
            if( ($s <= 60 && $s > 52) || ($s > 0 && $s < 2 )){
                $isfp = true;
            }else{
                $isfp = false;
            }
        }

        return $isfp;
    }

    /**
     * 修改总投注记录
     * @param $data
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function updateBetsRecord($data)
    {
        $type = [];
        foreach ( $data as $k=> $v ){
            switch ($k){
                case 'single':
                    $type[] = 'single';
                    break;
                case 'double':
                    $type[] = 'double';
                    break;
                case  'man':
                    $type[] = 'man';
                    break;
                case 'woman':
                    $type[] = 'woman';
                    break;
                case 'close':
                    $type[] = 'close';
                    break;
                case 'far':
                    $type[] = 'far';
                    break;
                case 'magic_y':
                    $type[] = 'magic_y';
                    break;
                case 'magic_n':
                    $type[] = 'magic_n';
                    break;
                case 'yemo':
                    $type[] = 'yemo';
                    break;
                case 'tianhui':
                    $type[] = 'tianhui';
                    break;
                case 'power':
                    $type[] = 'power';
                    break;
                case 'agile':
                    $type[] = 'agile';
                    break;
                case 'intellect':
                    $type[] = 'intellect';
                    break;
                default:
                    # code...
                    break;
            }


        }
        foreach ( $type as $item ){
            $betsRecord = BetsRecord::where('game',$data['game'])->where('index',$data['sequencenum'])->where('type',$item)->find();
            if( $betsRecord ){
                $betsRecord->money = $betsRecord['money'] + $data[$item];
                $betsRecord->save();
            }else{
                $betsRecord = new BetsRecord;
                $betsRecord->data([
                    'game'  =>  $data['game'],
                    'type'  =>  $item,
                    'money' =>  $data[$item],
                    'index' =>  $data['sequencenum'],
                    'site'          => $this->auth->site,
                    'createtime'    => time()
                ])->save();

            }
        }
    }

    /**
     * 给中奖用户上分
     * @param $game 游戏
     * @param $identifier 开奖结果
     * @param $index 期号
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function upUserScore($game,$identifier,$index)
    {
        $gameService = new GameService();
        $betsModel = new Bets;
        $now = time();

        if( $game == 'lol' || $game == 'pvp' || $game == 'dota2'){
            if( $game == 'lol' ){
                $gameodds = $gameService->getGameOdds('lolodds');
                $res = Db::name('game_lol')->where('identifier',$identifier)->find();//开奖英雄编号
                $res['magic'] = $res['magic'] == 1 ? 'magic_y' : 'magic_n';
            }elseif( $game == 'pvp' ){
                $gameodds = $gameService->getGameOdds('pvpodds');
                $res = Db::name('game_pvp')->where('identifier',$identifier)->find();//开奖英雄编号
                $res['magic'] = $res['magic'] == 1 ? 'magic_y' : 'magic_n';
            }elseif( $game == 'dota2' ){
                $gameodds = $gameService->getGameOdds('dota2odds');
                $res = Db::name('game_dota2')->where('identifier',$identifier)->find();//开奖英雄编号
            }


            $bets = Bets::where('sequencenum','=',$index)
                ->where('game','=',$game)
                ->where(function ($q){
                    //$q->whereOr('status','=',0)->whereOr('status',NULL);
                  	$q->whereOr('status',NULL);
                })->select();
            $updateBets = [];
            $zjmoney    = [];
            if( empty($bets) ){
                return false;//本期未投注或投注期号已开奖
            }
                foreach ($bets as $bet){
                    $content = json_decode($bet['content'],true);
                    foreach ( array_keys($content) as $item ){
                        if($game == 'dota2'){
                            switch ($item){
                                case $res['num']:   //单双中奖
                                    $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                    $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                                    break;
                                case $res['type']:  //攻击类型中奖
                                    $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                    $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                                    break;
                                case $res['attr']: //属性中奖
                                    $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                    $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                                    break;
                                case $res['line']: //阵营中奖
                                    $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];

                                    $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                                    break;
                                default:            //未中奖
                                    //todo
                                    $betsModel->where('id',$bet['id'])->update(
                                        ['status'=>0,'result'=>json_encode($res),'updatetime'=>$now]
                                    );//未中奖
                                    break;
                            }
                        }else{
                            if( $item == $res['sex'] ){ //性别中奖
                                $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                            }elseif( $item == $res['num'] ){ //单双中奖
                                $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                            }elseif( $item == $res['magic'] ){ //有无魔法值中奖
                                $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                            }elseif( $item == $res['type'] ){ //攻击类型中奖
                                $zjmoney[$bet['id']][] = (int)$content[$item] * (float)$gameodds[$item];
                                $updateBets[] = ['id'=>$bet['id'],'sequencenum'=>$bet['sequencenum'],'user_id'=>$bet['user_id'],'status'=>1];
                            }else{
                                $betsModel->where('id',$bet['id'])->update(
                                    ['status'=>0,'result'=>json_encode($res),'updatetime'=>$now]
                                );//未中奖
                            }
                        }
                    }

                }

                if( !empty($updateBets) ){
                    foreach ($updateBets as $k=>$updateBet){
                        $updateBets[$k]['zj_money']     = array_sum($zjmoney[$updateBet['id']]);
                        $updateBets[$k]['result']       = json_encode($res);
                        $updateBets[$k]['updatetime']   = $now;
                    }
                }


                $betsModel->saveAll(array_unique($updateBets, SORT_REGULAR));//修改投注中奖

                $toast   = 0;
                $newArr  = [];
                $user_ids = [];
                foreach ( $updateBets as $v ){
                    if( in_array($v['user_id'],$user_ids) ){
                        $toast += $v['zj_money'];
                    }else{
                        $toast = $v['zj_money'];

                    }
                    array_push($user_ids,$v['user_id']);
                    $newArr[$v['user_id']] = ['sequencenum'=>$index,'zj'=>$toast,'user_id'=>$v['user_id']];
                }


                foreach (array_unique($updateBets, SORT_REGULAR) as $v){
                    Wallet::where('user_id',$v['user_id'])->update([
                        'money' => Db::raw('money+'.$v['zj_money'])
                    ]);
                    $record_sn = checkRecordSn();
                    if( !isset($record_sn) || !$record_sn ){
                        $record_sn = date('ymdHis',time()) . mt_rand(1111,9999);
                    }
                    
                    WalletRecord::insert([
                        'record_sn' => $record_sn,
                        'user_id'   => $v['user_id'],
                        'type'      => 4,    //中奖上分
                        'money'     => $v['zj_money'],
                        'remark'    => '中奖',
                        'pay_status'=> 1,
                        'pay_time'  => $now,
                        'createtime'=> $now,
                        'index'     => $index
                    ]);
                    WalletLog::insert([
                        'record_sn' => $record_sn,
                        'user_id'   => $v['user_id'],
                        'change_money'=> '+'.$v['zj_money'],
                        'money'     => Wallet::where('user_id',$v['user_id'])->value('money'),
                        'remark'    => '中奖',
                        'createtime'=> $now,
                        'index'     => $index
                    ]);

                }
            return $newArr;
        }else{
            return false;
        }
    }
}